#include "graph.h"

namespace tbp {

/**
 * 数据格式：# upper_size lower_size
 * 要求下标从1开始，并且节点序号不超过upper_size或lower_size
 */
void BiGraph::BuildGraph(std::string path) {
  std::cout<<"path = "<<path<<"\n";
  std::ifstream infile;
  std::string tmp;
  infile.open(path);
  if (!infile.is_open()) {
    std::cout << "open file failed" << std::endl;
    exit(1);
  }
  // get the first line
  infile >> tmp >> this->upper_size_ >> this->lower_size_;
  // ========================debug=================================
  std::cout << this->upper_size_ << " : " << this->lower_size_ << "\n";
  // ========================debug=================================

  // 要求下标从1开始,多给一个slot
  this->upper_adj_.resize(this->upper_size_ + 1);
  this->upper_edge_time_.resize(this->upper_size_ + 1);
  this->upper_edge_time_set_.resize(this->upper_size_ + 1);
  this->upper_edge_time_set_end_.resize(this->upper_size_ + 1);

  this->lower_adj_.resize(this->lower_size_ + 1);
  this->lower_edge_time_.resize(this->lower_size_ + 1);

  uint32_t from, to, start, end;
  while (infile >> from >> to >> start >> end) {
#ifdef IDX_ZERO
    from++;
    to++;
#endif
    if (from > this->upper_size_ || to > this->lower_size_)
      continue;
    this->upper_adj_[from].emplace_back(to);
    this->lower_adj_[to].emplace_back(from);
    this->upper_edge_time_set_[from].insert(start);
    this->upper_edge_time_set_end_[from].insert(end);
    this->upper_edge_time_[from].emplace_back(start, end);
    this->lower_edge_time_[to].emplace_back(start, end);
    this->edge_size_++;
  }
  // 建图的时候就把节点序给算好
  compute_vertex_order();
  format();
  std::cout << "edge size = " << this->edge_size_ << "\n";
}

/**
 * 修改存储格式
 */
void BiGraph::format() {
  this->upper_edges_ = new uint32_t[this->edge_size_];
  this->lower_edges_ = new uint32_t[this->edge_size_];
  this->upper_times_ = new time_pair[this->edge_size_];
  this->lower_times_ = new time_pair[this->edge_size_];

  this->upper_degree_ = new uint32_t[this->upper_size_ + 1];
  this->lower_degree_ = new uint32_t[this->lower_size_ + 1];

  this->upper_degree_[0] = 0;
  this->lower_degree_[0] = 0;

  uint32_t idx = 0;
  uint32_t degree_total = 0;
  for (uint32_t i = 1; i <= this->upper_size_; i++) {
    uint32_t degree = this->upper_adj_[i].size();
    degree_total += degree;
    this->upper_degree_[i] = degree_total;
    for (uint32_t j = 0; j < degree; j++) {
      this->upper_edges_[idx] = this->upper_adj_[i][j];
      this->upper_times_[idx].first = this->upper_edge_time_[i][j].first;
      this->upper_times_[idx].second = this->upper_edge_time_[i][j].second;
      idx++;
    }
  }

  idx = 0;
  degree_total = 0;
  for (uint32_t i = 1; i <= this->lower_size_; i++) {
    uint32_t degree = this->lower_adj_[i].size();
    degree_total += degree;
    this->lower_degree_[i] = degree_total;
    for (uint32_t j = 0; j < degree; j++) {
      this->lower_edges_[idx] = this->lower_adj_[i][j];
      this->lower_times_[idx].first = this->lower_edge_time_[i][j].first;
      this->lower_times_[idx].second = this->lower_edge_time_[i][j].second;
      idx++;
    }
  }
  //==============debug==================
  // for (int i = 0; i <= this->upper_size_; i++) {
  //   std::cout << this->upper_degree_[i] << " ";
  // }
  // std::cout << "\n";
  // for (int i = 0; i < this->edge_size_; i++) {
  //   std::cout << this->upper_edges_[i] << " ";
  // }
  // std::cout << "\n";
  // for (int i = 0; i < this->edge_size_; i++) {
  //   std::cout << this->upper_times_[i].first << " ";
  // }
  // std::cout << "\n";
  //==============debug==================
}

// private：根据paper中描述，以degree作为全局节点序
void BiGraph::compute_vertex_order() {
  using vertex_pair = std::pair<uint32_t, uint32_t>;
  std::vector<vertex_pair> order_vec;

  // 下标从1开始
  for (int i = 1; i <= this->upper_size_; i++) {
    order_vec.emplace_back(i, this->upper_adj_[i].size());
  }
  // sort
  std::sort(order_vec.begin(), order_vec.end(),
            [](vertex_pair &first, vertex_pair &second) {
              if (first.second == second.second) {
                return first.first < second.first;
              }
              return first.second > second.second;
            });
  for (auto t : order_vec) {
    this->vertex_order_.push_back(t.first);
  }
}

/**
 * return by value
 */
std::vector<uint32_t> BiGraph::GetVertexOrder() { return this->vertex_order_; }

} // namespace tbp